package com.example.annotation.reflect

import android.view.View
import android.view.View.OnClickListener
import android.view.View.OnLongClickListener
import java.lang.reflect.Method
import java.lang.reflect.Proxy
import kotlin.reflect.KClass

object InjectUtils {
    fun inject(context: Any) {
        injectClick(context)
    }

    private fun injectClick(context: Any) {
        val clazz: Class<*> = context.javaClass
        //获取当前类的所有方法，也就是被绑定的Activity中的所有方法
        val methods = clazz.declaredMethods
        for (method in methods) {
            //遍历所有方法上的注解
            val annotations = method.annotations
            //方法上的注解可能有多个，所有这里也要用遍历
            for (annotation in annotations) {
                //获取注解的类名
                val annotationClass: Class<*> = annotation.annotationClass.java
                //判断这个注解类有没有被[EventBase]注解修饰
                val eventBase = annotationClass.getAnnotation(EventBase::class.java) ?: continue
                //判断是不是事件处理程序  onClick  onLongClink
                //                btn.setOnClickListener（new View.OnClickListener() {
//                    @Override
//                    public void onClick(View v) {
//
//                    }
//                });
                //1.setOnClickListener 订阅关系
//                String listenerSetter();
                val listenerSetter = eventBase.listenerSetter
                //2.new View.OnClickListener()  事件本身
//                Class<?> listenerType();
                val listenerType: Class<*> = eventBase.listenerType.java
                //3.事件处理程序
//                String callbackMethod();
                val callBackMethod = eventBase.callbackMethod

                //得到3要素之后，就可以执行代码了
                var valueMethod: Method? = null
                try {
                    /**
                     * 获取注解的value也就是[OnClick.value]和[OnLongClick.value]
                     */
                    valueMethod = annotationClass.getDeclaredMethod("value")
                    val viewId = valueMethod.invoke(annotation) as IntArray
                    /**
                     * [OnClick.value]和[OnLongClick.value]是可变参数，所有需要遍历出所有value。这里的value实际上就是view的id
                     */
                    for (id in viewId) {
                        //为了得到Button对象,使用findViewById
                        //使用反射得到findViewById方法
                        val findViewById =
                            clazz.getMethod("findViewById", Int::class.javaPrimitiveType)
                        //执行findViewById方法，获得view实例
                        val view = findViewById.invoke(context, id) as View ?: continue

                        /**
                         * 下边的代码属于动态代理，用动态代理的方法去执行[OnClickListener]和[OnLongClickListener]方法
                         */
                        //context===activity   click=method
                        val listenerInvocationHandler = ListenerInvocationHandler(context, method)
                        //new View.OnClickListener()
                        /**
                         * 动态代理
                         * Proxy.newProxyInstance(类加载器，代理的方法，真正执行的地方)
                         */
                        val proxy = Proxy.newProxyInstance(
                            listenerType.classLoader,
                            arrayOf(listenerType),
                            listenerInvocationHandler
                        )

                        //   view.setOnClickListener（new View.OnClickListener()）
                        //获得被代理的方法
                        val onClickMethod = view.javaClass.getMethod(listenerSetter, listenerType)
                        //将被代理的方法交给proxy
                        onClickMethod.invoke(view, proxy)
                    }
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        }
    }
}